package tms.presentation.bean.time;

import tms.business.time.TimeService;
import tms.model.time.TimeEntity;
import tms.util.activity.UserActivityManager;
import tms.util.constants.NavigationConstant;
import tms.util.constants.UiMessage;
import tms.util.helper.DateHelper;
import tms.util.jsf.FacesContextManager;
import tms.util.localization.LocalizationManager;
import tms.util.security.AppSecurityManager;

import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
import java.util.*;

@Named
@RequestScoped
public class TimeViewBean implements Serializable {
    @EJB
    private TimeService timeService;
    @Inject
    FacesContextManager facesContextManager;
    @Inject
    SessionScopedBean sessionScopedBean;
    @Inject
    LocalizationManager localizationManager;
    @Inject
    AppSecurityManager securityManager;
    @Inject
    UserActivityManager userActivityManager;    

    private List<TimeEntity> currentWeek;
    private List<Date> currentWeekDates;
    private TimeEntity currentTime;
    private String currentTimeClientId;
    private Date today = new Date();
    private Boolean hasPreviousWeek;
    private Boolean hasNextWeek;

    
    public List<TimeEntity> getCurrentWeek() {
        if (currentWeek == null) {
            if (securityManager.isLoggedIn()) {
                currentWeek = timeService.getCurrentWeekTimes(sessionScopedBean.getCurrentDate(), securityManager.getUser().getId(), localizationManager.getLocale());
            }
        }
        return currentWeek;
    }

    public void start() {
        timeService.startTime(securityManager.getUser().getId(), today);
        init();
        facesContextManager.navigateForOutcome(NavigationConstant.REDIRECT_TO_CURRENT_VIEW);
    }

    public void pause() {
        timeService.pauseTime(securityManager.getUser().getId());
        init();
    }

    public void play() {
        timeService.playTime(securityManager.getUser().getId(), today);
        init();
    }

    public void stop() {
        timeService.stopTime(securityManager.getUser().getId(), today);
        init();
    }

    public List<Date> getCurrentWeekDates() {
        if (currentWeekDates == null) {
            currentWeekDates = timeService.getCurrentWeek(sessionScopedBean.getCurrentDate(), localizationManager.getLocale());
        }
        return currentWeekDates;
    }

    public String getDayName(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, localizationManager.getLocale());
    }

    public TimeEntity getCurrentTime() {
        if (currentTime == null) {
            currentTime = timeService.getCurrentTime(securityManager.getUser().getId(), today);
        }
        return currentTime;
    }

    
    public Boolean isCurrentTime(TimeEntity timeEntity) {
        return timeService.isCurrentTime(timeEntity, today);
    }

    public TimeZone getCurrentTimeZone() {
        Calendar calendar = Calendar.getInstance(localizationManager.getLocale());
        return calendar.getTimeZone();
    }

    public void totalTimeEventListener(AjaxBehaviorEvent event) throws AbortProcessingException {
        Integer timeId = parseTimeId(event);
        Map<Integer, Boolean> timeStates = sessionScopedBean.getTimeStates();
        if (timeId > 0) {
            boolean isEditable = !timeStates.get(timeId);
            timeStates.put(timeId, isEditable);
            if (isEditable) {
                currentTimeClientId = event.getComponent().getClientId().replace("Label", "Input");
            } else {
                TimeEntity timeEntity = getTime(timeId);
                if (timeEntity != null) {
                    timeService.updateTime(timeEntity);
                    facesContextManager.addMessage(localizationManager.localizedMessage(UiMessage.TIME_UPDATED));
                }
            }
        }
        userActivityManager.userActive(securityManager.getUser().getId());
    }

    public String getCurrentTimeClientId() {
        return currentTimeClientId;
    }

    public boolean hasPreviousWeek() {
        if (hasPreviousWeek == null) {
            hasPreviousWeek = timeService.hasPreviousWeek(securityManager.getUser().getId(), sessionScopedBean.getCurrentDate(), localizationManager.getLocale());
        }
        return hasPreviousWeek;
    }

    public boolean hasNextWeek() {
        if (hasNextWeek == null) {
            Date currentWeekFirstDay = DateHelper.getDayBegin(timeService.getCurrentWeek(getToday(), localizationManager.getLocale()).get(0));
            hasNextWeek = timeService.hasNextWeek(securityManager.getUser().getId(), sessionScopedBean.getCurrentDate(), localizationManager.getLocale()) || sessionScopedBean.getCurrentDate().compareTo(currentWeekFirstDay) < 0;
        }
        return hasNextWeek;
    }

    public void showPreviousWeek() {
        List<Date> week = timeService.getCurrentWeek(sessionScopedBean.getCurrentDate(), localizationManager.getLocale());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(week.get(0));
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        sessionScopedBean.setCurrentDate(calendar.getTime());
        init();
        facesContextManager.navigateForOutcome(NavigationConstant.REDIRECT_TO_CURRENT_VIEW);
    }

    public void showNextWeek() {
        List<Date> week = timeService.getCurrentWeek(sessionScopedBean.getCurrentDate(), localizationManager.getLocale());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(week.get(week.size() - 1));
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        sessionScopedBean.setCurrentDate(calendar.getTime());
        init();
        facesContextManager.navigateForOutcome(NavigationConstant.REDIRECT_TO_CURRENT_VIEW);
    }

    public void showLastWeek() {
        Date lastDate = timeService.getLastStartDate(securityManager.getUser().getId());
        Date currentWeekFirstDay = DateHelper.getDayBegin(timeService.getCurrentWeek(getToday(), localizationManager.getLocale()).get(0));
        if (lastDate.compareTo(currentWeekFirstDay) < 0) {
            sessionScopedBean.setCurrentDate(currentWeekFirstDay);    
        } else {
            sessionScopedBean.setCurrentDate(lastDate);
        }
        init();
        facesContextManager.navigateForOutcome(NavigationConstant.REDIRECT_TO_CURRENT_VIEW);
    }

    public void changeUserLanguage(String code) {
        localizationManager.setLanguage(code);
        init();
        facesContextManager.navigateForOutcome(NavigationConstant.REDIRECT_TO_CURRENT_VIEW);
    }

    public Date getToday() {
        return today;
    }

    public long getWeekTotalTime() {
        long retVal = 0L;
        for (TimeEntity timeEntity : getCurrentWeek()) {
            if (timeEntity.getRunTime() != null) {
                retVal += timeEntity.getRunTime();
            }
        }
        return retVal;
    }


    private Integer parseTimeId(AjaxBehaviorEvent event) {
        String componentId = event.getComponent().getClientId();
        String timeId = componentId.substring(componentId.lastIndexOf('_') + 1, componentId.length());
        Integer retVal = null;
        try {
            retVal = Integer.parseInt(timeId);
        } catch (NumberFormatException e) {}
        return retVal;
    }

    private TimeEntity getTime(Integer id) {
        TimeEntity retVal = null;
        for (TimeEntity timeEntity : getCurrentWeek()) {
            if (timeEntity.getId().equals(id)) {
                retVal = timeEntity;
                break;
            }
        }
        return retVal;
    }

    private void init() {
        currentWeek = null;
        currentWeekDates = null;
        currentTimeClientId = null;
        currentTime = null;
        sessionScopedBean.resetTimeStates();
    }

}
